import html2canvas from 'html2canvas';

/**
 * * 判断是否是预览页
 * @returns boolean
 */
export const isPreview = () => {
	return document.location.hash.includes('preview');
};

/**
 * * 生成一个不重复的ID
 * @param { Number } randomLength
 */
export const getUUID = (randomLength = 10) => {
	return Number(Math.random().toString().substring(2, randomLength) + Date.now()).toString(36);
};

/**
 * 修改元素位置
 * @param target 对象
 * @param x X轴
 * @param y Y轴
 */
export const setComponentPosition = (target, x, y) => {
	x && (target.orgConfig.attr.x = x);
	y && (target.orgConfig.attr.y = y);
};

/**
 * * 设置元素属性
 * @param HTMLElement 元素
 * @param key 键名
 * @param value 键值
 */
export const setDomAttribute = (HTMLElement, key, value) => {
	if (HTMLElement) HTMLElement.style[key] = value;
};

/**
 * * file转url
 */
export const fileToUrl = (file) => {
	const Url = URL || window.URL || window.webkitURL;
	const ImageUrl = Url.createObjectURL(file);
	return ImageUrl;
};

/**
 * * file转base64
 */
export const fileTobase64 = (file, callback) => {
	let reader = new FileReader();
	reader.readAsDataURL(file);
	reader.onload = function (e) {
		if (e.target) {
			let base64 = e.target.result;
			callback(base64);
		}
	};
};

/**
 * *获取上传的文件数据
 * @param { File } file 文件对象
 */
export const readFile = (file) => {
	return new Promise((resolve) => {
		try {
			const reader = new FileReader();
			reader.onload = (evt) => {
				if (evt.target) resolve(evt.target.result);
			};
			reader.readAsText(file);
		} catch (error) {
			msgError('文件读取失败！');
		}
	});
};

/**
 * * 通过 a 标签下载数据
 * @param url
 * @param filename
 * @param fileSuffix
 */
export const downloadByA = (url, filename = new Date().getTime(), fileSuffix) => {
	const ele = document.createElement('a'); // 创建下载链接
	ele.download = `${filename}.${fileSuffix}`; //设置下载的名称
	ele.style.display = 'none'; // 隐藏的可下载链接
	// 字符内容转变成blob地址
	ele.href = url;
	// 绑定点击时间
	document.body.appendChild(ele);
	ele.click();
	// 然后移除
	document.body.removeChild(ele);
};

/**
 * * 下载数据
 * @param { string } content 数据内容
 * @param { ?string } filename 文件名称（默认随机字符）
 * @param { ?string } fileSuffix 文件名称（默认随机字符）
 */
export const downloadTextFile = (content, filename = new Date().getTime(), fileSuffix) => {
	// 字符内容转变成blob地址
	const blob = new Blob([content]);
	downloadByA(URL.createObjectURL(blob), filename, fileSuffix);
};

/**
 * * 截取画面为图片并下载
 * @param html 需要截取的 DOM
 */
export const canvasCut = (html, callback) => {
	if (!html) {
		msgError('导出失败！');
		if (callback) callback();
		return;
	}

	html2canvas(html, {
		backgroundColor: null,
		allowTaint: true,
		useCORS: true
	}).then((canvas) => {
		msgSuccess('导出成功！');
		downloadByA(canvas.toDataURL(), undefined, 'png');
		if (callback) callback();
	});
};

/**
 * * 处理请求事件单位
 * @param num 时间间隔
 * @param unit RequestHttpIntervalEnum
 * @return number 秒数
 */
export const intervalUnitHandle = (num, unit) => {
	switch (unit) {
		// 秒
		case '秒':
			return num * 1000;
		// 分
		case '分':
			return num * 1000 * 60;
		// 时
		case '时':
			return num * 1000 * 60 * 60;
		// 天
		case '天':
			return num * 1000 * 60 * 60 * 24;
		default:
			return num * 1000;
	}
};

/**
 * * JSON序列化，支持函数和 undefined
 * @param data
 */
export const JSONStringify = (data) => {
	return JSON.stringify(
		data,
		(key, val) => {
			// 处理函数丢失问题
			if (typeof val === 'function') {
				return `${val}`;
			}
			// 处理 undefined 丢失问题
			if (typeof val === 'undefined') {
				return null;
			}
			return val;
		},
		2
	);
};

export const evalFn = (fn) => {
	// var Fun = Function // 一个变量指向Function，防止前端编译工具报错
	return new Function('return ' + fn)();
};

// 自定义函数(动态获取对象二级(多级)属性(值))
export function GetProperty(obj, str) {
	try {
		let keyArray = str.replace(/\[(\w+)\]/g, '.$1').split('.'),
			data = '';
		keyArray.forEach((item, index) => {
			if (index === 0) {
				data = obj[item];
			} else {
				data = data?.[item];
			}
		});
		return data;
	} catch (error) {
		console.log(error);
	}
}

/**
 * * JSON反序列化，支持函数和 undefined
 * @param data
 */
// 内置字符串函数对象列表
export const excludeParseEventKeyList = [
	'vnodeMounted',
	'vnodeBeforeMount',
	'click',
	'dblclick',
	'mouseenter',
	'mouseleave',
	//过滤器
	'filter'
];

// 内置字符串函数键值列表
export const excludeParseEventValueList = [
	// 请求里的函数语句
	'javascript:'
];

export const JSONParse = (data) => {
	return JSON.parse(data, (k, v) => {
		// 过滤函数字符串
		if (excludeParseEventKeyList.includes(k)) return v;
		// 过滤函数值表达式
		if (typeof v === 'string') {
			const someValue = excludeParseEventValueList.some((excludeValue) => v.indexOf(excludeValue) > -1);
			if (someValue) return v;
		}
		// 还原函数值
		if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) {
			return evalFn(`(function(){return ${v}})()`);
		} else if (typeof v === 'string' && v.indexOf && v.indexOf('return ') > -1) {
			const baseLeftIndex = v.indexOf('(');
			if (baseLeftIndex > -1) {
				const newFn = `function ${v.substring(baseLeftIndex)}`;
				return evalFn(`(function(){return ${newFn}})()`);
			}
		}
		return v;
	});
};

/**
 * * 修改顶部标题
 * @param title
 */
export const setTitle = (title) => {
	title && (document.title = title);
};

// 转换为数字
export const toNumber = (number) => {
	return isString(number) ? parseFloat(parseFloat(number).toFixed(2)) : number;
};

// 转换为字符串
export const toString = (str) => {
	return isNumber(str) ? `${str}` : isObject(str) ? JSON.stringify(str) : str;
};

/**
 * * 函数过滤器
 * @param data 数据值
 * @param res 返回顶级对象
 * @param funcStr 函数字符串
 * @param isToString 是否转为字符串
 * @param errorCallBack 错误回调函数
 * @param successCallBack 成功回调函数
 * @returns
 */
export const newFunctionHandle = (data, res, funcStr, isToString, errorCallBack, successCallBack) => {
	try {
		if (!funcStr) return data;
		const fn = new Function('data', 'res', funcStr);
		const fnRes = fn(cloneDeep(data), cloneDeep(res));
		const resHandle = isToString ? toString(fnRes) : fnRes;
		// 成功回调
		successCallBack && successCallBack(resHandle);
		return resHandle;
	} catch (error) {
		// 失败回调
		errorCallBack && errorCallBack(error);
		return '函数执行错误';
	}
};

// * 动画
export const animationsClass = (animations) => {
	if (animations.length) return `animate__animated  animate__${animations[0]}`;
	return '';
};

// * 变换
export const getTransformStyle = (styles) => {
	const { opacity, rotateZ, rotateX, rotateY, skewX, skewY } = styles;
	return {
		opacity: opacity,
		transform: `rotateZ(${rotateZ || 0}deg) rotateX(${rotateX || 0}deg) rotateY(${rotateY || 0}deg) skewX(${skewX || 0}deg) skewY(${skewY || 0}deg)`
	};
};

// 获取组件样式
export const useComponentStyle = (attr) => {
	if (!attr) return {};
	return {
		// zIndex: attr.zIndex + 1,
		left: `${attr.x}px`,
		top: `${attr.y}px`
	};
};

// 获取实际宽高
export const useSizeStyle = (attr, scale) => {
	if (!attr) return {};
	return {
		zIndex: attr.zIndex + 1,
		width: `${scale ? scale * attr.w : attr.w}px`,
		height: `${scale ? scale * attr.h : attr.h}px`
	};
};

// 锚点位置
export const usePointStyle = (point, index, attr, cursorResize) => {
	const { w: width, h: height } = attr;

	const isTop = /t/.test(point);
	const isBottom = /b/.test(point);
	const isLeft = /l/.test(point);
	const isRight = /r/.test(point);

	let newLeft = 0;
	let newTop = 0;

	// 四个角的点
	if (point.length === 2) {
		newLeft = isLeft ? 0 : width;
		newTop = isTop ? 0 : height;
	} else {
		// 上下两点的点，宽度居中
		if (isTop || isBottom) {
			newLeft = width / 2;
			newTop = isTop ? 0 : height;
		}

		// 左右两边的点，高度居中
		if (isLeft || isRight) {
			newLeft = isLeft ? 0 : width;
			newTop = Math.floor(height / 2);
		}
	}

	const style = {
		left: `${newLeft}px`,
		top: `${newTop}px`,
		cursor: cursorResize[index] + '-resize'
	};

	return style;
};
